from .user.models import UserInfo
from .models import Roles, Menus, RoleMenus
from .serializers import UserInfoSerializer, RolesSerializer, MenusSerializer
from pkg.custom_model_view_set import CustomModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from django.http import JsonResponse
from rest_framework.views import APIView
from . import filter
from .models import Menus, UserRoles
from pkg.format_menu import format_menu
from rest_framework import status
from django.db import transaction


class UserInfoViewSet(CustomModelViewSet):
    queryset = UserInfo.objects.all()
    serializer_class = UserInfoSerializer

    filter_backends = (DjangoFilterBackend,)
    filter_class = filter.UserInfoFilter

    def create(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "data": [],
            "msg": "success"
        }
        try:
            # 拆分参数
            roles = request.data.get("roles")

            # 删除角色相关的参数
            request.data.pop("roles")

            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)

            # 用户绑定角色
            user_related_roles = []
            if len(roles) > 0:
                for r in roles:
                    user_related_roles.append(UserRoles(
                        user_id=serializer.data["id"],
                        role_id=r
                    ))
                UserRoles.objects.bulk_create(user_related_roles)

            res["data"] = serializer.data
        except Exception as e:
            res["code"] = 400
            res["msg"] = f"创建用户失败，{e}"

        return JsonResponse(res, status=status.HTTP_200_OK)

    def update(self, request, *args, **kwargs):

        res = {
            "code": 200,
            "data": [],
            "msg": "success"
        }

        try:

            # 拆分参数
            roles = request.data.get("roles")

            # 删除角色相关的参数
            request.data.pop("roles")

            partial = kwargs.pop('partial', False)
            instance = self.get_object()
            serializer = self.get_serializer(instance, data=request.data, partial=partial)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)

            if getattr(instance, '_prefetched_objects_cache', None):
                instance._prefetched_objects_cache = {}

            # 用户绑定角色
            user_related_roles = []
            if len(roles) > 0:
                with transaction.atomic():
                    UserRoles.objects.filter(user_id=serializer.data["id"]).delete()
                    for r in roles:
                        user_related_roles.append(UserRoles(
                            user_id=serializer.data["id"],
                            role_id=r
                        ))
                    UserRoles.objects.bulk_create(user_related_roles)
            res["data"] = serializer.data

        except Exception as e:
            res["code"] = 400
            res["msg"] = f"编辑用户失败，{e}"

        return JsonResponse(res, status=status.HTTP_200_OK)


class RolesViewSet(CustomModelViewSet):
    queryset = Roles.objects.all()
    serializer_class = RolesSerializer

    filter_backends = (DjangoFilterBackend,)
    filter_class = filter.RolesFilter


class MenusViewSet(CustomModelViewSet):
    queryset = Menus.objects.all()
    serializer_class = MenusSerializer

    filter_backends = (DjangoFilterBackend,)
    filter_class = filter.MenusFilter


class UserDetailsViews(APIView):
    def get(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "msg": "获取用户信息成功",
            "data": []
        }
        try:
            info = list(UserInfo.objects.filter(username=request.user.username).values())
            if len(info) > 0:
                info = info[0]
            else:
                info = {}
            res["data"] = info
        except Exception as e:
            res["code"] = 400
            res["msg"] = f"获取用户信息失败, {e}"

        return JsonResponse(res)


class MenuTreeViews(APIView):
    def get(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "msg": "获取菜单树成功",
            "data": []
        }

        try:
            # 递归获取菜单树
            def recursion_menu(menu, roles):
                m = format_menu(menu)
                r_string = []
                for r in roles:
                    r_string.append(str(r))
                menuRaw = Menus.objects.raw(
                    f"""select user_menus.* from user_menus left join user_role_related_menus on user_menus.id = user_role_related_menus.menu where user_role_related_menus.role in ({','.join(r_string)}) and user_menus.parent = {menu["id"]};""")

                m_list = []
                for mr in menuRaw:
                    d = {}
                    for mc in menuRaw.columns:
                        d[mc] = getattr(mr, mc)
                    m_list.append(d)
                tmp_m_list = []
                for i in m_list:
                    tmp_m_list.append(format_menu(i))
                    recursion_menu(i, roles)

                m["children"] = tmp_m_list
                return m

            # 查询用户角色
            userinfo = UserInfo.objects.get(username=request.user.username)
            roles = [r[0] for r in list(UserRoles.objects.filter(user_id=userinfo.id).values_list("role_id"))]

            # 查询当前角色的权限
            permissions = [p[0] for p in list(RoleMenus.objects.filter(role__in=roles).values_list("menu"))]
            menu_list = [p[0] for p in
                         list(Menus.objects.filter(id__in=permissions, menu_type=1).values_list("parent").distinct())]

            top_menu_list = list(Menus.objects.filter(id__in=menu_list).values())
            for i in top_menu_list:
                res["data"].append(recursion_menu(i, roles))

        except Exception as e:
            res["code"] = 400
            res["msg"] = f"获取菜单树失败, {e}"

        return JsonResponse(res)


class MenuListViews(APIView):
    def get(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "msg": "获取菜单树成功",
            "data": []
        }

        try:
            # 递归获取菜单树
            def recursion_menu(menu):
                m_list = list(Menus.objects.filter(parent=menu["id"]).values())
                for i in m_list:
                    recursion_menu(i)
                menu["children"] = m_list
                return menu

            # 查询出所有的顶级菜单
            top_menu_list = list(Menus.objects.filter(menu_type=1, parent=0).values())
            for i in top_menu_list:
                res["data"].append(recursion_menu(i))

        except Exception as e:
            res["code"] = 400
            res["msg"] = f"获取菜单树失败, {e}"

        return JsonResponse(res)


class RolePermViews(APIView):
    def post(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "msg": "更新角色权限",
            "data": []
        }

        try:
            role = request.data.get("role")
            menus = list(set(request.data.get("menus")))

            with transaction.atomic():

                # 删除角色对应的权限数据
                RoleMenus.objects.filter(role=role).delete()

                # 写入角色对应的数据
                role_menu = []
                for m in menus:
                    role_menu.append(RoleMenus(role=role, menu=m))
                RoleMenus.objects.bulk_create(role_menu)

        except Exception as e:
            res["code"] = 400
            res["msg"] = f"更新角色权限失败, {e}"

        return JsonResponse(res)


class RoleMenuListViews(APIView):
    def get(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "msg": "获取角色对应的权限列表",
            "data": []
        }

        try:
            role = request.GET.get("role")
            menus = [m[0] for m in list(RoleMenus.objects.filter(role=role).values_list("menu"))]
            res["data"] = menus
        except Exception as e:
            res["code"] = 400
            res["msg"] = f"更新角色权限失败, {e}"

        return JsonResponse(res)


class GetUserRoleViews(APIView):
    def get(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "msg": "获取用户的角色ID列表成功",
            "data": []
        }

        try:
            user_id = request.GET.get("user_id")
            roles = [r[0] for r in list(UserRoles.objects.filter(user_id=user_id).values_list("role_id"))]
            res["data"] = roles
        except Exception as e:
            res["code"] = 400
            res["msg"] = f"获取用户的角色ID列表失败, {e}"

        return JsonResponse(res)


class GetUserPermissions(APIView):
    def get(self, request, *args, **kwargs):
        res = {
            "code": 200,
            "msg": "获取用户权限成功",
            "data": []
        }

        try:

            # 查询用户信息
            userinfo = UserInfo.objects.get(username=request.user.username)

            # 获取用户角色
            role_ids = [r[0] for r in list(UserRoles.objects.filter(user_id=userinfo.id).values_list("role_id"))]

            # 查询所有角色的权限ID
            perm_ids = [p[0] for p in list(RoleMenus.objects.filter(role__in=role_ids).values_list("menu"))]

            # 查询权限标识列表
            permissions = [p[0] for p in list(Menus.objects.filter(id__in=perm_ids).values_list("permission")) if
                           p[0] != None]

            res["data"] = permissions

        except Exception as e:
            res["code"] = 400
            res["msg"] = f"获取用户的角色ID列表失败, {e}"

        return JsonResponse(res)
